﻿using BJ.AuthDomain.Commands;
using BJ.AuthDomain.IService;
using BJ.AuthEntity.DtoModels;
using BJ.AuthEntity.Models;
using BJ.AuthEntity.ViewModels;
using Mapster;
using Syspetro.Core.AppDeal;
using Syspetro.Core.CommandBus;
using Syspetro.Core.DbAccessor;
using Syspetro.Core.Encrypt;
using Syspetro.Deploy.FreeSqlDb;
using Syspetro.Deploy.Jwt;
using Syspetro.Deploy.Managers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BJ.AuthDomain.Service
{
    public class AdminUserAuthService : EntityBaseService<AdminUserAuth>, IAdminUserAuthService
    {
        readonly IFreeSql _freeSql;
        readonly IJwtService _JwtService;
        readonly IRepository<AdminUserAuth> repository;
        readonly IAuthorizationManager _authorization;
        readonly ICommandBus _command;
        readonly IAdminUserService _userService;

        public AdminUserAuthService(IFreeSql freeSql, IJwtService jwtservice,  ICommandBus command, IAuthorizationManager authorization, IAdminUserService userService
)
        {
            _freeSql = freeSql;
            _JwtService = jwtservice;
            _authorization = authorization;
            _command = command;
            this.repository = new FreeSqlRepository<AdminUserAuth>(freeSql);
            _userService = userService;
        }
        public override IRepository<AdminUserAuth> Repository
        {
            get
            {
                return repository;
            }
        }
        public async Task<SpActionResult<VM_Token>> AuthLoginUser(VM_AdminAuthLogin authLogin)
        {
            var user = await GetUserAsync(authLogin.Account);
            if (user == null) return new SpActionResult<VM_Token> { Success = false, Msg = "用户不存在" };
            if (string.IsNullOrEmpty(authLogin.Code))
            {
                return new SpActionResult<VM_Token> { Success = false, Msg = "请输入Google验证码" };
            }
            else
            {
                var userdto = user.Adapt<UserAuthDto>();
                var res = _command.Send(new GoogleVerifyCommand { UserId = user.Id, IsAdmin = true, Captcha = authLogin.Code });
                if (res.Success)
                {
                    var check = _command.Send(new PswdCheckCommand { Pswd = authLogin.Password, Md5Pswd = user.Password });
                    if (!check.Success)
                    {
                        //密码更新,老用户密码加密方式导致更新账户不能登录
                        var newcheck = _command.Send(new PswdCheckCommand { Account = authLogin.Account,  Pswd = authLogin.Password, Md5Pswd = user.Password });
                        if (!newcheck.Success)
                        {
                            return new SpActionResult<VM_Token> { Success = false, Msg = check.Msg };
                        }
                    }
                    var token = this._JwtService.GetToken(userdto);
                    var vmUser = new VM_Token { Token = token.Item2, TokenId = token.Item1, Uid = user.Id };
                    user.LoginTime = DateTime.Now;
                    await Repository.UpdateAsync(user, t => t.LoginTime);
                    return new SpActionResult<VM_Token>(vmUser);
                }
                return new SpActionResult<VM_Token> { Success = res.Success, Msg = res.Msg };
            }
        }
        public async Task<SpActionResult<Guid>> LoginUser(VM_AdminLogin loginUser)
        {
            var user = await GetUserAsync(loginUser.Account);
            if (user == null) return new SpActionResult<Guid> { Success = false, Msg = "用户不存在" };
            var check = _command.Send(new PswdCheckCommand { Pswd = loginUser.Password, Md5Pswd = user.Password });
            if (!check.Success)
            {
                return new SpActionResult<Guid> { Success = false, Msg = check.Msg };
            }
            return new SpActionResult<Guid>(user.Id);
        }
        public async Task<SpActionResult<bool>> ChangePswd(VM_ChangePswd changePswd)
        {
            var acc = _authorization.GetUserName;
            var user = await GetUserAsync(acc);
            if (user == null) return new SpActionResult<bool> { Success = false, Msg = "用户不存在" };
            var check = _command.Send(new PswdCheckCommand { Pswd = changePswd.Pswd_Old, Md5Pswd = user.Password });
            if (!check.Success)
            {
                return new SpActionResult<bool> { Success = false, Msg = check.Msg };
            }
            return new SpActionResult<bool>(await DoChangePswd(changePswd, user.Id));
        }
        public async Task<SpActionResult<VM_User>> GetUserInfo()
        {
            var acc = _authorization.GetUserId;
            if (acc == Guid.Empty) return new SpActionResult<VM_User> { Success = false, Msg = "用户不存在" };
            var vm_User = await _userService.GetUserFull(acc);
            return new SpActionResult<VM_User>(vm_User);
        }
        public Task LogOut(Guid tokenId)
        {
            return Task.Run(() => { _JwtService.RemoveToken(tokenId); });
        }
        public Task<string> RefreshToken(Guid tokenId)
        {
            return Task.FromResult(_JwtService.RefreshToken(tokenId));
        }
        private async Task<bool> DoChangePswd(VM_ChangePswd changePswd,Guid uid)
        {
            var pswd = _command.Send(new PswdMd5Command { Pswd = changePswd.Pswd_New});
            if (!pswd.Success)
                return false;
            var Password = pswd.Get().Data;
            if (await _freeSql.Update<AdminUserAuth>().Set(t => new UserAuth { Password = Password }).UpdateColumns(t => t.Password).Where(t => t.Id == uid).ExecuteAffrowsAsync() > 0)
                return true;
            return false;
        }
        private async Task<AdminUserAuth> GetUserAsync(string Account)
        {
            AdminUserAuth user = await _freeSql.Select<AdminUserAuth>()
                .Include(t => t.User)
                .Include(t => t.User.Role)
                .Where(t => t.Account == Account)
                .FirstAsync();
            return user;
        }
        public async Task<List<VM_Menu>> GetAuthMenus()
        {
            var id = _authorization.GetUserId;
            var user =await _freeSql.Select<AdminUser>().Where(d=>d.Id==id).ToOneAsync();
            var MenuAuth = _freeSql.Select<MenuAuth>().Where(t => t.RoleId == user.RoleId).ToList().Select(t => t.MenuId).ToList();

            var ss = await _freeSql.Select<Menu>().Where(t => t.Enable).OrderBy(d=>d.Sort).Where(t => MenuAuth.Contains(t.Id)).ToTreeListAsync();
            return ss.Adapt<List<VM_Menu>>();
        }
    }
}
